/************************************************************************************
**  
* @copyright (c) 2015-, Technology Co., LTD. All Right Reserved.
*
*************************************************************************************/
/**
* @file     duye_cap_packet.cpp
* @version     
* @brief      
* @author   
* @date     2013-04-07
* @note 
*
*  1. 2018-04-07 created this file
* 
*/
#include <duye_logger.h>
#include <duye_cap_packet.h>

static const int8* DUYE_LOG_PREFIX = "duye.cap.packet";

namespace duye {

Packet::Packet() 
	: m_pktTime(0)
	, m_rawData(NULL)
	, m_rawDataLen(0)
	, m_linkLayerHeader(NULL) 
	, m_netLayerHeader(NULL) 
	, m_tfLayerHeader(NULL)
	, m_data(NULL) {}

Packet::~Packet() {
	delete m_linkLayerHeader; 
	delete m_netLayerHeader; 
	delete m_tfLayerHeader; 
	if (m_data) {
		free(m_data);
		m_data = NULL;
	}
}

bool Packet::parserPkt(uint8* data, const uint32 dataLen) {
	m_linkLayerHeader = LinkLayerHeader::createHeader(data, dataLen);
	if (m_linkLayerHeader == NULL || !m_linkLayerHeader->parserHeader(data, dataLen)) {
		DUYE_ERROR("parser link layer header failed");
		return false;
	}

	m_netLayerHeader = NetLayerHeader::createHeader(m_linkLayerHeader->getUpperProtocol());
	if (m_netLayerHeader == NULL || 
		!m_netLayerHeader->parserHeader(m_linkLayerHeader->getPayload(), m_linkLayerHeader->getPayloadLen())) {
		DUYE_WARN("parser net layer header error, or have no net layser");
		return true;
	}

	m_tfLayerHeader = TfLayerHeader::createHeader(m_netLayerHeader->getUpperProtocol());
	if (m_tfLayerHeader == NULL ||
		!m_tfLayerHeader->parserHeader(m_netLayerHeader->getPayload(), m_netLayerHeader->getPayloadLen())) {
		DUYE_WARN("parser transfer layer header error, or have no transfer layser");
		return true;
	}
		
	return true;
}

void Packet::setPcapPkthdr(const PcapPkthdr& hdr) {
	::memcpy(&m_pcapPkthdr, &hdr, sizeof(PcapPkthdr));
}

const PcapPkthdr& Packet::getPcapPkthdr() const {
	return m_pcapPkthdr;
}

void Packet::setPktTime(const uint64 pktTime) { m_pktTime = pktTime; }
uint64 Packet::getPktTime() const { return m_pktTime; }

void Packet::setRawData(uint8* data) { m_rawData = data; }
const uint8* Packet::getRawData() { return m_rawData; }

void Packet::setRawDataLen(uint32 len) { m_rawDataLen = len; }
uint32 Packet::getRawDataLen() { return m_rawDataLen; }

const LinkLayerHeader* Packet::getLinkLayerHeader() { return m_linkLayerHeader; }
const NetLayerHeader* Packet::getNetLayerHeader() { return m_netLayerHeader; }
const TfLayerHeader* Packet::getTfLayerHeader() { return m_tfLayerHeader; }

uint8* Packet::getSrcMac() const {
	if (m_linkLayerHeader) {
		return m_linkLayerHeader->getSrcMacAddr(); 
	}

	return NULL;
}

uint8* Packet::getDstMac() const {
	if (m_linkLayerHeader) {
		return m_linkLayerHeader->getDstMacAddr(); 
	}

	return NULL;
}

uint32 Packet::getSrcIP() const {
	if (m_netLayerHeader) {
		return m_netLayerHeader->getSrcIPAddr(); 
	}

	return 0;
}

uint32 Packet::getDstIP() const {
	if (m_netLayerHeader) {
		return m_netLayerHeader->getDstIPAddr(); 
	}

	return 0;
}

uint16 Packet::getSrcPort() const {
	if (m_tfLayerHeader) {
		return m_tfLayerHeader->getSrcPort(); 
	}

	return 0;
}

uint16 Packet::getDstPort() const {
	if (m_tfLayerHeader) {
		return m_tfLayerHeader->getDstPort(); 
	}

	return 0;
}

ProtocolType Packet::getLinkLayerProto() const {
	if (m_linkLayerHeader) {
		return m_linkLayerHeader->getCurrProtocol(); 
	}

	return PROTO_NUKNOWN;
}

ProtocolType Packet::getNetLayerProto() const {
	if (m_netLayerHeader) {
		return m_netLayerHeader->getCurrProtocol(); 
	}

	return PROTO_NUKNOWN;
}

ProtocolType Packet::getTfLayerProto() const {
	if (m_tfLayerHeader) {
		return m_tfLayerHeader->getCurrProtocol(); 
	}

	return PROTO_NUKNOWN;
}

bool Packet::cache() {
	m_data = static_cast<uint8*>(::malloc(m_rawDataLen));
	if (!m_data) {
		return false;
	}
	
	::memcpy(m_data, m_rawData, m_rawDataLen);
	m_rawData = m_data;
	return parserPkt(m_rawData, m_rawDataLen);
}

}
